/* model */
import Field from "@model/entity/Field";
/* enum */
import { FieldTypeMappingEnum } from "@model/enum/FieldMappingEnum";
import { 
  SettingGPTQuestionListFieldEventNameEnum, 
  SettingGPTQuestionListFieldNameEnum, 
  SettingGPTRobotListFieldEventNameEnum, 
  SettingGPTRobotListFieldNameEnum, 
  SettingGPTServiceTypeEnum, 
  SettingGPTServiceTypeEnumCNNameEnum, 
  SettingGPTStatusCNNmaeEnum, 
  SettingGPTStatusEnum 
} from "@src/modules/setting/gpt/model/enum";
/* utils */
import { cloneDeep, isFalsy } from "@src/util/type";
import { dispatch } from '@src/util/emitter'
/* types */
import { 
  SettingGPTQuestionItemType, 
  SettingGPTQuestionSourceDocumentType, 
  SettingGPTRobotConfigType, 
  SettingGPTRobotModuleConfigType, 
  SettingGPTRobotModuleType, 
  SettingGPTRobotType
} from "@src/modules/setting/gpt/types";
import ComponentNameEnum from "@model/enum/ComponentNameEnum";
/* utils */
import { findComponentUpward } from "@src/util/assist";
import { openTabForWikiView } from "@src/util/business/openTab";
import { isRobotSystem } from "@src/modules/setting/gpt/utils";
import { parse_with_default_value } from "@src/util/lang/object";
import { concat } from "@src/util/lang/string";
import { getRootWindowInitData } from "@src/util/window";
import { setClipboardData } from '@src/util/dom'
import { message } from "@src/util/message";
import platform from '@src/platform'

const SettingGPTQuestionListChatTypeField: Field = {
  displayName: "类型",
  fieldName: SettingGPTQuestionListFieldNameEnum.ChatType,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false)
}

const SettingGPTQuestionListQuestionField: Field = {
  displayName: "问题",
  fieldName: SettingGPTQuestionListFieldNameEnum.Question,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  width: 240
}

const SettingGPTQuestionListAnswerField: Field = {
  displayName: "回复答案",
  fieldName: SettingGPTQuestionListFieldNameEnum.Answer,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  // width: 300,
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    
    const answer = row.answer || ''
    
    return (
      <div 
        class="setting-gpt-question-view-table__answer"
        // @ts-ignore
        domPropsInnerHTML={answer}
      >
      </div>
    )
    
  }
}

const SettingGPTQuestionListSupplementaryAnswerField: Field = {
  displayName: "方案",
  fieldName: SettingGPTQuestionListFieldNameEnum.SupplementaryAnswer,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(true)
}

const SettingGPTQuestionListQuestionUserField: Field = {
  displayName: "提问人",
  fieldName: SettingGPTQuestionListFieldNameEnum.QuestionUser,
  formType: FieldTypeMappingEnum.User,
  width: 120,
  isNull: Number(true)
}

const SettingGPTQuestionListCreateUserField: Field = {
  displayName: "提问人",
  fieldName: SettingGPTQuestionListFieldNameEnum.CreateUser,
  formType: FieldTypeMappingEnum.User,
  width: 120,
  isNull: Number(true),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    const createUser = row.createUser || {}
    const name = createUser.displayName || '-'
    return name
  }
}

const SettingGPTQuestionListCreateTimeField: Field = {
  displayName: "创建时间",
  fieldName: SettingGPTQuestionListFieldNameEnum.CreateTime,
  formType: FieldTypeMappingEnum.DateTime,
  width: 180,
  isNull: Number(false)
}

const SettingGPTQuestionListQuestionTimeField: Field = {
  displayName: "提问时间",
  fieldName: SettingGPTQuestionListFieldNameEnum.CreateTime,
  formType: FieldTypeMappingEnum.DateTime,
  width: 180,
  isNull: Number(false)
}

const SettingGPTQuestionListUpdateTimeField: Field = {
  displayName: "更新时间",
  fieldName: SettingGPTQuestionListFieldNameEnum.UpdateTime,
  formType: FieldTypeMappingEnum.DateTime,
  width: 180,
  isNull: Number(false)
}

const SettingGPTQuestionListStatusField: Field = {
  displayName: "状态",
  fieldName: SettingGPTQuestionListFieldNameEnum.Status,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    const status = row.status as SettingGPTStatusEnum
    return SettingGPTStatusCNNmaeEnum[status]
  }
}

const SettingGPTQuestionListSimilarQuestionField: Field = {
  displayName: "相似问题",
  fieldName: SettingGPTQuestionListFieldNameEnum.SimilarQuestionList,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(true),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    const similarQuestionList = row.similarQuestionList || []
    const similarQuestionListString = similarQuestionList.join(', ')
    return similarQuestionListString
  }
}

const SettingGPTQuestionListRobotField: Field = {
  displayName: "AI机器人名称",
  fieldName: SettingGPTQuestionListFieldNameEnum.Robot,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(true),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    const robot = row.robot || {}
    const name = robot.name || ''
    return name
  }
}

const SettingGPTQuestionListSourceField: Field = {
  displayName: "问题来源",
  fieldName: SettingGPTQuestionListFieldNameEnum.Source,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    const createUser = row.createUser || {}
    const createUserId = createUser.userId || ''
    const robot = row.robot || {}
    const robotName = robot.name || ''
    const notSystemSource = robotName || '外部链接'
    const systemSource = robotName || '售后宝系统'
    
    return createUserId ? systemSource : notSystemSource
  }
}

const SettingGPTQuestionListApplyRobotListField: Field = {
  displayName: "应用至",
  fieldName: SettingGPTQuestionListFieldNameEnum.ApplyRobotList,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(true),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    
    const applyRobotList = (row.applyRobotList || []) as unknown as { name: string, id: string }[]
    const applyRobotNameList = applyRobotList.map(robot => {
      return robot.name
    })
    const applyRobotNameListString = applyRobotNameList.join(', ')
    
    return applyRobotNameListString
  }
}

const SettingGPTQuestionListApplyRobotAppField: Field = {
  displayName: "应用来源",
  fieldName: SettingGPTQuestionListFieldNameEnum.RobotApp,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(true),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    
    const robotAppType = row.shbGptRobotApp?.type || ''
    const robotAppTypeName = SettingGPTServiceTypeEnumCNNameEnum[robotAppType] || ''
    
    return robotAppTypeName
  }
}

const SettingGPTQuestionListSourceDocumentListField: Field = {
  displayName: "文章来源",
  fieldName: SettingGPTQuestionListFieldNameEnum.SourceDocumentList,
  formType: FieldTypeMappingEnum.Text,
  width: 180,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTQuestionItemType) => {
    
    const onClickHandler = (id: string, url: string) => {
      
      const isHttpsUrl = url?.startsWith('https')
      
      if (isHttpsUrl) {
        platform.openLink(url)
        return
      }
      
      openTabForWikiView(id)
    }
    
    const renderTag = (sourceDocument: SettingGPTQuestionSourceDocumentType) => {
      
      const url = sourceDocument.url
      const name = sourceDocument.name
      const id = sourceDocument.id
      
      
      return (
        <el-tag onClick={() => onClickHandler(id, url)}>
          { name }
        </el-tag>
      )
    }
    
    const sourceDocumentListJSON = row.sourceDocumentList
    
    let sourceDocumentList: SettingGPTQuestionSourceDocumentType[] = []
    
    try {
      sourceDocumentList = parse_with_default_value(sourceDocumentListJSON, [])
    } catch (error) {
      console.error(error)
      return ''
    }
    
    return (
      <div class="setting-gpt-question-view-table__source-document-list">
        { 
          sourceDocumentList.map((sourceDocument: SettingGPTQuestionSourceDocumentType) => {
            return renderTag(sourceDocument)
          })
        }
      </div>
    )
  }
}

const SettingGPTQuestionListOperationField: Field = {
  displayName: "操作",
  fieldName: SettingGPTQuestionListFieldNameEnum.Operation,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  width: 180,
  renderCell: (h, column, row: SettingGPTQuestionItemType, tableInstance) => {
    
    const questionTableComponentName = ComponentNameEnum.SettingGPTQuestionViewTable
    const addedAnswer = row.addedAnswer
    const addAnswerButtonText = '添加至'
    
    const questionTableComponent = findComponentUpward(tableInstance, questionTableComponentName)
    const isLikeActive = Boolean(questionTableComponent?.isLikeActive)
    const isShowDelete = Boolean(questionTableComponent?.isShowDelete)
    const isAllowCreate = Boolean(questionTableComponent?.isAllowCreate)
    
    const dispatchEvent = (event: string, ...args: any[]) => {
      dispatch.call(tableInstance, questionTableComponentName, event, ...args)
    }
    
    const addAnswerHandler = () => {
      dispatchEvent(SettingGPTQuestionListFieldEventNameEnum.AddAnswer, row)
    }
    
    const addWikiHandler = () => {
      dispatchEvent(SettingGPTQuestionListFieldEventNameEnum.AddWiki, row)
    }
    
    const addAnswerButton = () => {
      
      if (isFalsy(isAllowCreate)) {
        return
      }
      
      return (
        <el-popover
          popper-class="setting-gpt-view-question-popper"
          trigger="hover"
        >
          
          <el-button
            slot="reference"
            class="setting-gpt-question-view-table__add-button"
            type="text"
            size="mini"
          >
            { addAnswerButtonText }
          </el-button>
          
          <div 
            class="setting-gpt-view-question-popper-item"
            onClick={addAnswerHandler}
          >
            应用百科
          </div>
          
          <div 
            class="setting-gpt-view-question-popper-item"
            onClick={addWikiHandler}
          >
            知识库
          </div>
          
        </el-popover>
      )
      
    }
    
    const deleteHandler = () => {
      dispatchEvent(SettingGPTQuestionListFieldEventNameEnum.Delete, row)
    }
    
    const deleteButton = () => {
      
      if (isFalsy(isShowDelete)) {
        return
      }
      
      return (
        <el-button
          class="setting-gpt-question-view-table__delete-button"
          type="text"
          size="mini"
          onClick={deleteHandler}
        >
          删除
        </el-button>
      )
    }
    
    return (
      <div>
        { addAnswerButton() }
        { deleteButton() }
      </div>
    )
  }
}

const SettingGPTManageQuestionListOperationField: Field = {
  displayName: "操作",
  fieldName: SettingGPTQuestionListFieldNameEnum.Operation,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  width: 180,
  renderCell: (h, column, row: SettingGPTQuestionItemType, tableInstance) => {
    
    const questionTableComponentName = ComponentNameEnum.SettingGPTQuestionViewTable
    const editButtonText = '编辑'
    
    const questionTableComponent = findComponentUpward(tableInstance, questionTableComponentName)
    const isShowDelete = Boolean(questionTableComponent?.isShowDelete)
    const isAllowEdit = Boolean(questionTableComponent?.isAllowEdit)
    
    const dispatchEvent = (event: string, ...args: any[]) => {
      dispatch.call(tableInstance, questionTableComponentName, event, ...args)
    }
    
    const editButtonHandler = () => {
      dispatchEvent(SettingGPTQuestionListFieldEventNameEnum.Edit, row)
    }
    
    const editButton = () => {
      
      if (isFalsy(isAllowEdit)) {
        return
      }
      
      return (
        <el-button
          class="setting-gpt-question-view-table__add-button"
          type="text"
          size="mini"
          onClick={editButtonHandler}
        >
          { editButtonText }
        </el-button>
      )
    }
    
    const deleteHandler = () => {
      dispatchEvent(SettingGPTQuestionListFieldEventNameEnum.Delete, row)
    }
    
    const deleteButton = () => {
      
      if (isFalsy(isShowDelete)) {
        return
      }
      
      return (
        <el-button
          class="setting-gpt-question-view-table__delete-button"
          type="text"
          size="mini"
          onClick={deleteHandler}
        >
          删除
        </el-button>
      )
    }
    
    return (
      <div>
        { editButton() }
        { deleteButton() }
      </div>
    )
  }
}

const SettingGPTRobotListNameField: Field = {
  displayName: "AI机器人名称",
  fieldName: SettingGPTRobotListFieldNameEnum.Name,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    const name = row.name
    const isSystem = isRobotSystem(row)
    
    const renderTag = () => {
      
      if (isFalsy(isSystem)) {
        return
      }
      
      return (
        <el-tag type="primary">
          系统
        </el-tag>
      )
      
    }
    
    return (
      <div class="setting-gpt-robot-view-table__name">
        { name }
        { renderTag() }
      </div>
    )
    
  }
}

const SettingGPTRobotListUrlField: Field = {
  displayName: "机器人链接",
  fieldName: SettingGPTRobotListFieldNameEnum.Url,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderHeader: (h, column, tableInstance) => {
    
    const robotTableComponentName = ComponentNameEnum.SettingGPTSettingViewRobotTable
    
    const openUrlDescriptionDialog = () => {
      dispatch.call(tableInstance, robotTableComponentName, SettingGPTRobotListFieldEventNameEnum.UrlDescriptionDialog)
    }
    
    return (
      <div class="setting-gpt-robot-view-table__url">
        { SettingGPTRobotListUrlField.displayName }
        <i 
          class="iconfont icon-info"
          onClick={openUrlDescriptionDialog}
        >
        </i>
      </div>
    )
  },
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    const id = row.id
    const rootWindowInitData = getRootWindowInitData()
    const tenantId = rootWindowInitData?.user?.tenantId || ''
    const robotId = id
    const url = `/shb/home/setting/gpt/chat?tenantId=${tenantId}&robotId=${robotId}`
    const origin = window.location.origin
    const fullUrl = `${origin}${url}`
    
    const copyHandler = () => {
      setClipboardData(fullUrl, () => {
        message.success('复制成功')
      })
    }
    
    const copyButton = () => {
      return (
        <el-button
          class="setting-gpt-robot-view-table__copy-button"
          type="text"
          size="mini"
          onClick={copyHandler}
        >
          复制
        </el-button>
      )
    }
    
    const copyIcon = () => {
      return (
        <i 
          class="setting-gpt-robot-view-table__copy-button iconfont icon-file-copy"
          onClick={copyHandler}
        >
        </i>
      )
    }
    
    const onUrlClick = () => {
      platform.openLink(fullUrl)
    }
    
    return (
      <div class="setting-gpt-robot-view-table__url">
        { copyIcon() }
        <div 
          class="setting-gpt-robot-view-table__url-text"
          onClick={onUrlClick}
        >
          { fullUrl }
        </div>
      </div>
    )
    
  }
}

const SettingGPTRobotListAppListField: Field = {
  displayName: "应用服务",
  minWidth: '220',
  fieldName: SettingGPTRobotListFieldNameEnum.ShbGptRobotAppVOList,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    // 机器人应用列表
    const appList = row?.shbGptRobotAppVOList || []
    // 机器人应用类型列表
    const appTypeList = appList.map(app => app.type).filter(Boolean)
    // 机器人应用中文名列表
    const cnNameList = appTypeList.map(type => SettingGPTServiceTypeEnumCNNameEnum[type])
    // 机器人应用中文名列表字符串
    const appTypeListString = cnNameList.join('、')
    
    return (
      <div class="setting-gpt-robot-view-table__app-list">
        { appTypeListString }
      </div>
    )
    
  }
}

const SettingGPTRobotListSwitchField: Field = {
  displayName: "启用/禁用",
  width: 160,
  fieldName: SettingGPTRobotListFieldNameEnum.Switch,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType, tableInstance) => {
    
    const robotTableComponentName = ComponentNameEnum.SettingGPTSettingViewRobotTable
    
    const isSystem = isRobotSystem(row)
    
    const dispatchEvent = (event: string, ...args: any[]) => {
      dispatch.call(tableInstance, robotTableComponentName, event, ...args)
    }
    
    const switchHandler = (value: boolean) => {
      dispatchEvent(SettingGPTRobotListFieldEventNameEnum.Switch, {
        row: row,
        value: Number(value)
      })
    }
    
    const switchButton = () => {
      
      return (
        <el-switch
          value={Boolean(row.enable)}
          onChange={switchHandler}  
        >
        </el-switch>
      )
    }
    
    return (
      <div>
        { switchButton() }
      </div>
    )
  }
}

const SettingGPTRobotListSourceInsideField: Field = {
  displayName: "数据来源-内部模块",
  fieldName: SettingGPTRobotListFieldNameEnum.SourceInside,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    const setting: SettingGPTRobotConfigType = parse_with_default_value(row.setting, {} as SettingGPTRobotConfigType)
    const insideModuleConfig: SettingGPTRobotModuleConfigType  = setting.insideModuleConfig || {} 
    const modules: SettingGPTRobotModuleType[] = insideModuleConfig.modules || []
    
    const enableModules = modules.filter(module => module.enable)
    const moduleNames = enableModules.map(module => {
      return module.name
    })
    
    return concat(moduleNames, '，')
    
  }
}

const SettingGPTRobotListSourceOutsideAppField: Field = {
  displayName: "数据来源-外部应用",
  fieldName: SettingGPTRobotListFieldNameEnum.SourceOutsideApp,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    const setting: SettingGPTRobotConfigType = parse_with_default_value(row.setting, {} as SettingGPTRobotConfigType)
    const outsideModuleConfig: SettingGPTRobotModuleConfigType  = setting.outsideModuleConfig || {} 
    const modules: SettingGPTRobotModuleType[] = outsideModuleConfig.modules || []
    
    const enableModules = modules.filter(module => module.enable)
    const moduleNames = enableModules.map(module => {
      return module.name
    })
    
    return concat(moduleNames, '，')
    
  }
}

const SettingGPTRobotListModelField: Field = {
  displayName: "公共模型",
  fieldName: SettingGPTRobotListFieldNameEnum.Model,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  renderCell: (h, column, row: SettingGPTRobotType) => {
    
    const setting: SettingGPTRobotConfigType = parse_with_default_value(row.setting, {} as SettingGPTRobotConfigType)
    const commonModuleConfig: SettingGPTRobotModuleConfigType  = setting.commonModuleConfig || {} 
    const modules: SettingGPTRobotModuleType[] = commonModuleConfig.modules || []
    
    const enableModules = modules.filter(module => module.enable)
    const moduleNames = enableModules.map(module => {
      return module.name
    })
    
    return concat(moduleNames, '，')
    
  }
}

const SettingGPTRobotListOperationField: Field = {
  displayName: "操作",
  fieldName: SettingGPTRobotListFieldNameEnum.Operation,
  formType: FieldTypeMappingEnum.Text,
  isNull: Number(false),
  fixed: 'right',
  renderCell: (h, column, row: SettingGPTRobotType, tableInstance) => {
    
    const robotTableComponentName = ComponentNameEnum.SettingGPTSettingViewRobotTable
    
    const robotTableComponent = findComponentUpward(tableInstance, robotTableComponentName)
    const isAllowEdit = Boolean(robotTableComponent?.isAllowEdit)
    
    const isSystem = isRobotSystem(row)
    
    const dispatchEvent = (event: string, ...args: any[]) => {
      dispatch.call(tableInstance, robotTableComponentName, event, ...args)
    }
    
    const editHandler = () => {
      dispatchEvent(SettingGPTRobotListFieldEventNameEnum.Edit, row)
    }
    
    const editButton = () => {
      
      if (isSystem) {
        return
      }
      
      return (
        <el-button
          class="setting-gpt-robot-view-table__edit-button"
          type="text"
          size="mini"
          onClick={editHandler}
        >
          重命名
        </el-button>
      )
    }
    
    const deleteHandler = () => {
      dispatchEvent(SettingGPTRobotListFieldEventNameEnum.Delete, row)
    }
    
    const deleteButton = () => {
      
      if (isSystem) {
        return
      }
      
      return (
        <el-button
          class="setting-gpt-robot-view-table__delete-button"
          type="text"
          size="mini"
          onClick={deleteHandler}
        >
          删除
        </el-button>
      )
    }
    
    const settingHandler = () => {
      dispatchEvent(SettingGPTRobotListFieldEventNameEnum.Setting, row)
    }
    
    const settingButton = () => {
      return (
        <el-button
          class="setting-gpt-robot-view-table__setting-button"
          type="text"
          size="mini"
          onClick={settingHandler}
        >
          设置
        </el-button>
      )
    }
    
    return (
      <div>
        { editButton() }
        { settingButton() }
        { deleteButton() }
      </div>
    )
  }
  
}

const SettingGPTQuestionListFields: Field[] = [
  SettingGPTQuestionListQuestionField,
  SettingGPTQuestionListAnswerField,
  SettingGPTQuestionListApplyRobotAppField,
  SettingGPTQuestionListSourceDocumentListField,
  SettingGPTQuestionListQuestionUserField,
  SettingGPTQuestionListCreateTimeField,
  SettingGPTQuestionListOperationField
].map((field: Field) => {
  
  const _field = cloneDeep(field)
  _field.isSystem = Number(true)
  
  return _field
  
})

const SettingGPTManageQuestionListFields: Field[] = [
  SettingGPTQuestionListQuestionField,
  SettingGPTQuestionListSimilarQuestionField,
  SettingGPTQuestionListAnswerField,
  SettingGPTQuestionListUpdateTimeField,
  SettingGPTManageQuestionListOperationField
].map((field: Field) => {
  
  const _field = cloneDeep(field)
  _field.isSystem = Number(true)
  
  return _field
  
})

const SettingGPTQuestionLogListFields: Field[] = [
  SettingGPTQuestionListSourceField,
  SettingGPTQuestionListQuestionField,
  SettingGPTQuestionListAnswerField,
  SettingGPTQuestionListCreateUserField,
  SettingGPTQuestionListQuestionTimeField
].map((field: Field) => {
  
  const _field = cloneDeep(field)
  _field.isSystem = Number(true)
  
  return _field
  
})

const SettingGPTRobotListFields: Field[] = [
  SettingGPTRobotListNameField,
  SettingGPTRobotListUrlField,
  SettingGPTRobotListAppListField,
  SettingGPTRobotListSwitchField,
  SettingGPTRobotListOperationField
].map((field: Field) => {
  
  const _field = cloneDeep(field)
  _field.isSystem = Number(true)
  
  return _field
  
})

export {
  SettingGPTQuestionListFields,
  SettingGPTQuestionLogListFields,
  SettingGPTRobotListFields,
  SettingGPTManageQuestionListFields
}